<template>
  <div class="qr-scanner-overlay fixed inset-0 bg-black/70 z-50 flex items-center justify-center">
    <div class="relative w-full max-w-md p-4">
      <!-- 扫描框 -->
      <div v-if="!errorMessage" class="relative aspect-square mx-auto bg-transparent border-2 border-white/50 rounded-lg">
        <!-- 扫描区域指示 -->
        <div class="absolute inset-4 bg-white/10 rounded-md">
          <!-- 扫描线动画 -->
          <div class="absolute left-0 right-0 h-0.5 bg-primary animate-scan"></div>
          
          <!-- 扫描区域角落 -->
          <div class="absolute top-0 left-0 w-8 h-8 border-t-2 border-l-2 border-primary"></div>
          <div class="absolute top-0 right-0 w-8 h-8 border-t-2 border-r-2 border-primary"></div>
          <div class="absolute bottom-0 left-0 w-8 h-8 border-b-2 border-l-2 border-primary"></div>
          <div class="absolute bottom-0 right-0 w-8 h-8 border-b-2 border-r-2 border-primary"></div>
        </div>
        
        <!-- 视频元素 -->
        <video ref="video" class="absolute inset-0 w-full h-full object-cover rounded-lg"></video>
      </div>
      
      <!-- 错误消息 -->
      <div v-else class="bg-white/10 backdrop-blur-sm rounded-lg p-6 text-center mx-auto max-w-xs">
        <div class="text-5xl mb-4">
          <i class="fa fa-camera text-primary"></i>
        </div>
        <h3 class="text-white text-xl font-medium mb-2">摄像头访问权限</h3>
        <p class="text-gray-300 mb-6">{{ errorMessage }}</p>
        <div class="flex flex-col gap-3">
          <button 
            class="bg-primary hover:bg-primary/90 text-white py-3 px-6 rounded-full font-medium transition-colors"
            @click="retryScanner"
          >
            重试
          </button>
          <button 
            class="bg-white/10 hover:bg-white/20 text-white py-3 px-6 rounded-full font-medium transition-colors"
            @click="closeScanner"
          >
            取消
          </button>
        </div>
      </div>
      
      <!-- 提示文字 -->
      <div v-if="!errorMessage" class="text-center mt-6 text-white">
        <p class="text-lg font-medium mb-2">将二维码对准扫描框</p>
        <p class="text-gray-300 text-sm">保持光线充足，距离5-10厘米</p>
      </div>
      
      <!-- 取消按钮 -->
      <button 
        v-if="!errorMessage"
        class="absolute -top-16 right-0 w-10 h-10 bg-white/10 rounded-full flex items-center justify-center text-white hover:bg-white/20 transition-colors"
        @click="closeScanner"
      >
        <i class="fa fa-times text-xl"></i>
      </button>
    </div>
  </div>
</template>

<script>
import jsQR from 'jsqr';

export default {
  name: 'QRCodeScanner',
  emits: ['scan-result', 'close'],
  data() {
    return {
      stream: null,
      canvas: null,
      canvasContext: null,
      scanning: false,
      errorMessage: ''
    };
  },
  mounted() {
    this.initScanner();
  },
  beforeUnmount() {
    this.stopScanner();
  },
  methods: {
    async initScanner() {
      try {
        // 重置错误消息
        this.errorMessage = '';
        
        // 创建canvas元素用于图像处理
        this.canvas = document.createElement('canvas');
        this.canvasContext = this.canvas.getContext('2d');
        
        // 请求摄像头权限并获取视频流
        // 为移动设备提供更多配置选项以提高兼容性
        this.stream = await navigator.mediaDevices.getUserMedia({
          video: {
            facingMode: { exact: 'environment' }, // 优先使用后置摄像头
            width: { ideal: 1280 },
            height: { ideal: 720 },
            frameRate: { ideal: 30, min: 10 }
          }
        });
        
        // 设置视频元素
        const video = this.$refs.video;
        video.srcObject = this.stream;
        
        // 等待视频元数据加载完成
        await new Promise(resolve => {
          video.onloadedmetadata = resolve;
        });
        
        // 设置canvas尺寸
        this.canvas.width = video.videoWidth;
        this.canvas.height = video.videoHeight;
        
        // 开始扫描
        this.scanning = true;
        this.startScanning();
      } catch (error) {
        console.error('初始化扫描器失败:', error);
        
        // 根据错误类型提供更具体的提示
        if (error.name === 'NotAllowedError' || error.name === 'PermissionDeniedError') {
          this.errorMessage = '请在手机设置中允许此应用访问您的摄像头，然后重试。';
        } else if (error.name === 'NotFoundError' || error.name === 'DevicesNotFoundError') {
          this.errorMessage = '未检测到可用的摄像头设备。';
        } else if (error.name === 'NotReadableError') {
          this.errorMessage = '摄像头被其他应用占用，请关闭其他应用后重试。';
        } else if (error.name === 'OverconstrainedError') {
          // 如果严格要求后置摄像头失败，尝试不指定摄像头类型
          try {
            this.stream = await navigator.mediaDevices.getUserMedia({
              video: { width: { ideal: 1280 }, height: { ideal: 720 } }
            });
            const video = this.$refs.video;
            video.srcObject = this.stream;
            await new Promise(resolve => { video.onloadedmetadata = resolve; });
            this.canvas.width = video.videoWidth;
            this.canvas.height = video.videoHeight;
            this.scanning = true;
            this.startScanning();
            return;
          } catch (fallbackError) {
            console.error('使用备用配置也失败:', fallbackError);
            this.errorMessage = '无法访问摄像头，请确保已授予权限并尝试重新打开应用。';
          }
        } else {
          this.errorMessage = '无法访问摄像头，请确保已授予权限。';
        }
      }
    },
    
    retryScanner() {
      // 尝试重新初始化扫描器
      this.initScanner();
    },
    
    startScanning() {
      const scan = () => {
        if (!this.scanning) return;
        
        const video = this.$refs.video;
        
        // 在canvas上绘制当前视频帧
        this.canvasContext.drawImage(video, 0, 0, this.canvas.width, this.canvas.height);
        
        // 获取图像数据
        const imageData = this.canvasContext.getImageData(0, 0, this.canvas.width, this.canvas.height);
        
        // 使用jsQR库解析QR码
        const code = jsQR(imageData.data, imageData.width, imageData.height, {
          inversionAttempts: 'dontInvert',
        });
        
        // 如果解析到QR码
        if (code) {
          this.handleScanResult(code.data);
        } else {
          // 继续扫描
          requestAnimationFrame(scan);
        }
      };
      
      // 开始扫描循环
      requestAnimationFrame(scan);
    },
    
    handleScanResult(result) {
      this.scanning = false;
      this.stopScanner();
      
      // 发射扫描结果事件
      this.$emit('scan-result', result);
      
      // 关闭扫描器
      this.closeScanner();
    },
    
    stopScanner() {
      this.scanning = false;
      
      // 停止视频流
      if (this.stream) {
        this.stream.getTracks().forEach(track => {
          track.stop();
        });
        this.stream = null;
      }
      
      // 清空视频源
      if (this.$refs.video) {
        this.$refs.video.srcObject = null;
      }
    },
    
    closeScanner() {
      this.stopScanner();
      // 重置错误消息
      this.errorMessage = '';
      this.$emit('close');
    }
  }
};
</script>

<style scoped>
/* 扫描线动画 */
@keyframes scan {
  0% {
    top: 0;
  }
  100% {
    top: 100%;
  }
}

.animate-scan {
  animation: scan 2s linear infinite;
}
</style>